package baiqi.sishen.community.service;

import baiqi.sishen.community.dto.QueryQuestionDTO;
import baiqi.sishen.community.dto.QuestionDTO;
import baiqi.sishen.community.enums.SortEnum;
import baiqi.sishen.community.enums.ThumbTypeEnum;
import baiqi.sishen.community.execption.CustomizeErrorCode;
import baiqi.sishen.community.execption.CustomizeException;
import baiqi.sishen.community.mapper.QuestionExtMapper;
import baiqi.sishen.community.mapper.QuestionMapper;
import baiqi.sishen.community.mapper.ThumbMapper;
import baiqi.sishen.community.mapper.UserMapper;
import baiqi.sishen.community.model.*;
import baiqi.sishen.community.utils.NavigatePagesUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 兕神
 * @version 1.0
 * DateTime: 2023/4/28
 */
@Service
public class QuestionService {

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private QuestionExtMapper questionExtMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private ThumbMapper thumbMapper;

    /**
     * 问题的插入或更新
     *
     * @param question question
     */
    public void insertOrUpdate(Question question) {
        if (question.getId() == null) {
            //问题不存在，插入问题
            question.setGmtCreate(System.currentTimeMillis());
            question.setGmtModified(question.getGmtCreate());
            question.setGmtLatestComment(question.getGmtCreate());
            question.setCommentCount(0);
            question.setLikeCount(0);
            question.setViewCount(0);
            question.setStatus(0);
            questionMapper.insert(question);
        } else {
            //问题存在，更新数据
            question.setGmtModified(System.currentTimeMillis());
            QuestionExample example = new QuestionExample();
            example.createCriteria()
                    .andIdEqualTo(question.getId());
            int result = questionMapper.updateByExampleSelective(question, example);
            if (result == 0) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }
        }
    }

    /**
     * 问题数据的查询
     *
     * @param sort   排序规则
     * @param tag    热门标签
     * @param search 搜索条件
     * @param page   当前页
     * @param size   页容量
     * @return PageInfo<QuestionDTO>
     */
    public PageInfo<QuestionDTO> list(String sort, String tag, String search, Integer page, Integer size) {
        //获取问题查询类
        QueryQuestionDTO queryQuestionDTO = getQueryQuestionDTO(sort, tag, search);

        PageHelper.startPage(page, size);
        List<Question> projectVOList = questionExtMapper.selectQuestionBySearch(queryQuestionDTO);

        return getQuestionDTOPageInfo(page, projectVOList);
    }

    /**
     * 根据下列三个条件获取问题查询类
     *
     * @param sort   排序规则
     * @param tag    热门标签
     * @param search 搜索条件
     * @return QueryQuestionDTO
     */
    private QueryQuestionDTO getQueryQuestionDTO(String sort, String tag, String search) {
        //拼接成正则表达式
        if (StringUtils.isNotBlank(search)) {
            String[] split = StringUtils.split(search, " ");
            search = Arrays.stream(split)
                    .filter(StringUtils::isNotBlank)
                    .map(t -> t.replace("+", "").replace("?", "").replace("*", ""))
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.joining("|"));
        }

        QueryQuestionDTO queryQuestionDTO = new QueryQuestionDTO();
        queryQuestionDTO.setSearch(search);
        if (StringUtils.isNotBlank(tag)) {
            queryQuestionDTO.setTag(tag.replace("+", "").replace("?", "").replace("*", ""));
        }
        //设定sort 和time
        for (SortEnum sortEnum : SortEnum.values()) {
            if (sortEnum.name().toLowerCase().equals(sort)) {
                queryQuestionDTO.setSort(sort);
                if (sortEnum == SortEnum.HOT7) {
                    queryQuestionDTO.setTime(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 7);
                }
                if (sortEnum == SortEnum.HOT30) {
                    queryQuestionDTO.setTime(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30);
                }
                break;
            }
        }
        return queryQuestionDTO;
    }

    /**
     * 获取用户自己的提问
     *
     * @param userId 用户id
     * @param page   当前页码
     * @param size   页容量
     * @return PageInfo<QuestionDTO>
     */
    public PageInfo<QuestionDTO> list(Long userId, Integer page, Integer size) {

        QuestionExample questionExample = new QuestionExample();
        questionExample.createCriteria()
                .andCreatorEqualTo(userId);
        questionExample.setOrderByClause("gmt_modified desc");

        PageHelper.startPage(page, size);
        List<Question> projectVOList = questionMapper.selectByExampleWithBLOBs(questionExample);
        return getQuestionDTOPageInfo(page, projectVOList);
    }

    /**
     * 获取PageInfo<QuestionDTO>
     *
     * @param page      当前页码
     * @param questions 查询问题集
     * @return PageInfo<QuestionDTO>
     */
    private PageInfo<QuestionDTO> getQuestionDTOPageInfo(Integer page, List<Question> questions) {
        PageInfo<Question> pageInfo = new PageInfo(questions);
        PageInfo<QuestionDTO> questionDTOPageInfo = new PageInfo<>();
        BeanUtils.copyProperties(pageInfo, questionDTOPageInfo, "list");
        //导航页
        int[] ints = NavigatePagesUtil.getNavigatePages(page, questionDTOPageInfo.getPages());
        questionDTOPageInfo.setNavigatepageNums(ints);

        //填充信息
        ArrayList<QuestionDTO> questionDTOS = new ArrayList<>();
        for (int i = 0; i < pageInfo.getList().size(); i++) {
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(pageInfo.getList().get(i), questionDTO);
            //设置用户信息
            User user = userMapper.selectByPrimaryKey(questionDTO.getCreator());
            questionDTO.setUser(user);
            questionDTOS.add(questionDTO);
        }
        questionDTOPageInfo.setList(questionDTOS);
        return questionDTOPageInfo;
    }

    /**
     * 根据id 获取问题
     *
     * @param id 问题id
     * @return Question
     */
    public QuestionDTO getQuestionById(Long id) {
        QuestionDTO questionDTO = new QuestionDTO();
        QuestionExample questionExample = new QuestionExample();
        questionExample.createCriteria()
                .andIdEqualTo(id);
        List<Question> questions = questionMapper.selectByExampleWithBLOBs(questionExample);

        if (questions.size() == 0) {
            throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
        }
        Question question = questions.get(0);

        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdEqualTo(question.getCreator());
        List<User> users = userMapper.selectByExample(userExample);
        BeanUtils.copyProperties(question, questionDTO);
        User user = users.get(0);
        if (user == null) {
            throw new CustomizeException(CustomizeErrorCode.USER_NOT_FOUND);
        }
        questionDTO.setUser(user);
        return questionDTO;
    }

    /**
     * 增加阅读数
     *
     * @param id 问题id
     */
    public void incViewCount(Long id) {
        Question question = new Question();
        question.setId(id);
        question.setViewCount(1);
        questionExtMapper.incViewCount(question);

    }

    /**
     * 用于查询相关问题
     *
     * @param query QuestionDTO
     * @return List<Question>
     */
    public List<Question> selectRelated(QuestionDTO query) {
        if (query == null) {
            return new ArrayList<>();
        }

        //根据逗号分离
        String[] split = StringUtils.split(query.getTag(), ",");
        //用|做分隔成正则表达式
        String tags = String.join("|", split);

        //填充id和tag
        Question question = new Question();
        question.setId(query.getId());
        question.setTag(tags);

        List<Question> relatedQuestions = questionExtMapper.selectRelated(question);
        return relatedQuestions;
    }

    /**
     * 查询首页置顶问题数据
     *
     * @param sort   排序规则
     * @param tag    热门标签
     * @param search 搜索条件
     * @return List<QuestionDTO>
     */
    public List<QuestionDTO> listTop(String sort, String tag, String search) {
        //获取问题查询类
        QueryQuestionDTO queryQuestionDTO = getQueryQuestionDTO(sort, tag, search);

        //查询置顶问题
        ArrayList<QuestionDTO> questionDTOS = new ArrayList<>();
        List<Question> questions = questionExtMapper.selectTopQuestion(queryQuestionDTO);

        //填充问题创建者
        for (Question question : questions) {
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(question, questionDTO);
            User user = userMapper.selectByPrimaryKey(question.getCreator());
            questionDTO.setUser(user);
            questionDTOS.add(questionDTO);
        }
        return questionDTOS;
    }

    /**
     * 获取当前登录者的收藏问题
     *
     * @param userId 当前登录者id
     * @param page   当前页码
     * @param size   页容量
     * @return PageInfo<QuestionDTO>
     */
    public PageInfo<QuestionDTO> listLikes(Long userId, Integer page, Integer size) {

        ThumbExample thumbExample = new ThumbExample();
        thumbExample.createCriteria()
                .andTypeEqualTo(ThumbTypeEnum.QUESTION.getType())
                .andLikerEqualTo(userId);
        List<Thumb> thumbs = thumbMapper.selectByExample(thumbExample);

        //获取评论者的id并去重
        Set<Long> set = thumbs.stream().map(Thumb::getTargetId).collect(Collectors.toSet());
        ArrayList<Long> questionIds = new ArrayList<>(set);

        PageHelper.startPage(page,size);
        QuestionExample questionExample = new QuestionExample();
        questionExample.createCriteria()
                .andIdIn(questionIds);
        List<Question> questions = questionMapper.selectByExampleWithBLOBs(questionExample);
        return getQuestionDTOPageInfo(page,questions);
    }
}

